package lib4app;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import socket.UDP;
import struct.SensorData;
import util.Util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.concurrent.CompletableFuture;

public abstract class AbstractApp implements App {
    protected Log logger = LogFactory.getLog(AbstractApp.class);
    protected String appName;
    protected String appDescription;

    public AbstractApp() {
        appName = getClass().getName();
        appDescription = "This is " + appName + ".";
        configApp();
        Util.configLog4j();
    }

    private GetValueThread getValueThread = null;
    public class GetValueThread extends Thread {
        private volatile boolean shouldStop = false;
        private volatile boolean stopped = true;
        private final int udpPort;

        public GetValueThread(int udpPort) {
            this.udpPort = udpPort;
        }

        public void run() {
            stopped = false;
            while (!shouldStop) {
                JSONObject sensorJson = JSON.parseObject(UDP.recv(udpPort, 2000));
                if (sensorJson != null) {
                    String channel = sensorJson.getString("channel");
                    String msg = sensorJson.getString("msg");
                    logger.info(String.format("[%s]: getMsg(%s, %s)", appName, channel, msg));
                    CompletableFuture.runAsync(() -> {
                        getMsg(channel, SensorData.fromJSONString(msg));
                    });
                }
            }
            stopped = true;
        }

        public void stopThread() {
            shouldStop = true;
            while (!stopped) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            UDP.close(udpPort);
        }
    }

    public void startGetValueThread(int udpPort) {
        if (getValueThread == null) {
            getValueThread = new GetValueThread(udpPort);
            getValueThread.start();
        }
    }

    public void stopGetValueThread() {
        if (getValueThread != null) {
            getValueThread.stopThread();
            getValueThread = null;
        }
    }
}
